package demo.log.log4j2;

import com.ximalaya.xdcs.client.logimpl.LogEventDes;
import org.apache.commons.lang.StringUtils;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.core.impl.ThrowableProxy;
import demo.log.model.GenericLogEvent;
import org.apache.logging.log4j.core.LogEvent;

import java.io.PrintWriter;
import java.io.StringWriter;

public class Log4j2EventAdapter implements GenericLogEvent {

    private final LogEvent event;

    public Log4j2EventAdapter(LogEvent event) {
        this.event = event;
    }

    @Override
    public LogEventDes parseLogEvent() {
        if (event == null){
            return null;
        }

        Level logLevel = Level.toLevel(null, Level.ERROR);
        if (event.getLevel().intLevel() < logLevel.intLevel()){
            return null;
        }

        LogEventDes logEventDes = new LogEventDes();
        try {
            logEventDes.setLogLevelDes(event.getLevel().toString());
            logEventDes.setLogDetail(String.valueOf(event.getMessage()));
            logEventDes.setThreadName(event.getThreadName());
            logEventDes.setLogName(event.getLoggerName());
            if(event.getMessage() != null){
                logEventDes.setMessage(event.getMessage().getFormattedMessage());
            }

            if (Level.ERROR.equals(event.getLevel())) {

                Throwable errorInfo = event.getThrown();
                ThrowableProxy throwableProxy = event.getThrownProxy();
                if (errorInfo != null) {
                    // 获得抛出异常的方法名称
                    StackTraceElement[] stackTrace = errorInfo.getStackTrace();
                    String errorClassName = errorInfo.getClass().getName();
                    logEventDes.setLogIdentity(errorClassName);
                    StringWriter buf = new StringWriter();
                    errorInfo.printStackTrace(new PrintWriter(buf));
                    logEventDes.setLogDetail(buf.toString());
                    // 获得抛出异常的方法名称
                    if (stackTrace.length == 0) {
                        logEventDes.setMethodName("unknown");
                    } else {
                        StackTraceElement lastElem = stackTrace[0]; // ArrayOutOfBoundException
                        logEventDes.setMethodName(lastElem.getClassName() + ":" + lastElem.getMethodName());
                        logEventDes.setLogIdentity(lastElem.getClassName() + ":" + lastElem.getMethodName() + ":" + lastElem.getLineNumber());
                    }
                }

                if(StringUtils.isBlank(logEventDes.getLogIdentity())){
                    logEventDes.setLogIdentity(event.getLoggerName());
                    logEventDes.setMethodName(event.getLoggerName());
                }
                if (StringUtils.isBlank(logEventDes.getLogIdentity())) {
                    logEventDes.setLogIdentity("unknown");
                    logEventDes.setMethodName("unknown");
                }
            }

        } catch (Throwable ex) {
            ex.printStackTrace();
        }

        return logEventDes;
    }
}
